/**
  ******************************************************************************
  * @file    main.c
  * @author  ashuai0110
  * @version V2.0
  * @date    2024-09-12
  * @brief   使用举例-AT指令交互
  *
  ******************************************************************************
  * @attention
  *
  * 版权声明:内容为编者(ashuai0110)原创,使用请注明出处,当然,你也可以不这样做^_^
  * 出处链接:https://gitee.com/ashuai0110/mcu_reuse_development_module
  *
  ******************************************************************************
  */

/* 包含头文件-----------------------------------------------------------------*/
#include "bsp.h"

#include "uart_handler.h"
#include "command_at.h"

/* 私有宏定义-----------------------------------------------------------------*/
#define _USE_CMD_AT_WAY                         (1u) /* AT指令交互处理方式选择 0:搜索帧头帧尾的方式  1:外部接收标志的方式 */

#define CMD_AT_HEAD                             "AT+" /* 帧头 */
#define CMD_AT_TAIL                             "\r\n" /* 帧尾 */

/* 私有类型定义---------------------------------------------------------------*/

/* 私有变量-------------------------------------------------------------------*/
static uint8_t txBuf[128]; /* 串口管理所需发送缓冲区 */
static uint8_t rxBuf[128]; /* 串口管理所需接收缓冲区 */
static uart_handler_t usart1Hr; /* 串口管理实例 */
static cmd_at_t CmdAT; /* AT指令交互管理实例 */

/* 全局变量-------------------------------------------------------------------*/

/* 私有函数原型---------------------------------------------------------------*/


/**
  * @brief  This function handles SysTick Handler.
  *
  * @param  None
  *
  * @retval None
  */
void SysTick_Handler(void)
{
    /* 组件计时节拍接口 */
    mw_tick_inc(1);
}

/**
  * @brief  串口中断函数
  *
  * @param  None
  *
  * @retval None
  */
void USART1_IRQHandler(void)
{
    static uint8_t rxData, txData, ret;
    
    if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)
    {
        rxData = USART_ReceiveData(USART1);
        /* 写入接收缓存 */
        ret = uart_hr_write_rx_buf(&usart1Hr, &rxData, 1);
        if(0 == ret)
        {
            MW_WARN_LOG("uart_hr_write_rx_buf failure");
        }
        
        USART_ClearITPendingBit(USART1, USART_IT_RXNE);
    }
    
    if(USART_GetITStatus(USART1, USART_IT_TXE) != RESET)
    {
        /* 读出发送缓存 */
        ret = uart_hr_read_tx_buf(&usart1Hr, &txData, 1);
        if(1 == ret)
        {
            USART_SendData(USART1, txData);
        }
        
        USART_ClearITPendingBit(USART1, USART_IT_TXE);
    }
}

/**
  * @brief  AT指令交互用户写数据接口
  *
  * @param  data : 数据缓冲区
  *
  * @param  len  : 写入的数据长度
  *
  * @retval 实际写入的长度
  */
uint32_t cmd_at_write_user(void *data, uint32_t len)
{
    return uart_hr_write_tx_buf(&usart1Hr, data, len);
}

/**
  * @brief  AT指令交互用户读数据接口
  *
  * @param  buf : 数据缓存区
  *
  * @param  len : 读出的数据长度
  *
  * @retval 实际读出的长度
  */
uint32_t cmd_at_read_user(void *buf, uint32_t len)
{
    return uart_hr_read_rx_buf(&usart1Hr, buf, len);
}

/**
  * @brief  main
  */
int main(int argc, char *argv[])
{
    static uint8_t ret, state;
    
    MW_VER_LOG("example-command_at", 2, 0, 0);
    
    /* BSP初始化 */
    bsp_init();
    
    /* 串口管理初始化 帧间隔100ms 接收超时时间2000ms */
    uart_hr_init(&usart1Hr, txBuf, sizeof(txBuf), rxBuf, sizeof(rxBuf), bsp_usart1_tx_en, 100, 2000);
    /* AT指令交互初始化 回复超时时间1000ms 超时重发次数2次 */
    cmd_at_init(&CmdAT, CMD_AT_HEAD, CMD_AT_TAIL, cmd_at_read_user, cmd_at_write_user, 1000, 2);
    
#if (!_USE_CMD_AT_WAY)
    /* AT指令交互(阻塞式) */
    ret = cmd_at_process_block(&CmdAT, CMD_AT_RESERVE, CMD_AT_WAY_SEARCH, "AT+OK\r\n", "AT+NAME=%s\r\n", "ashuai0110");
    if(ret != MW_RET_OK)
    {
        MW_ERROR_LOG("cmd_at_process_block return %s! rsp data:%s", ret == MW_RET_ERR ? "error" : "timeout", cmd_at_rsp_data(&CmdAT));
    }
#endif
    
    state = 1; /* 开启轮询式处理 */
    
    while(1)
    {
        /* 串口管理轮询处理 */
        ret = uart_hr_poll(&usart1Hr);
        
#if (_USE_CMD_AT_WAY)
        /* 接收完成 */
        if(MW_RET_OK == ret)
        {
            cmd_at_set_rec_flag(&CmdAT); /* 设置外部接收标志 */
            MW_DEBUG_LOG("uart rec complate");
        } /* 接收超时 无需求可忽略此返回值 */
        else if(MW_RET_TIMEOUT == ret)
        {
            MW_WARN_LOG("uart rec timeout");
        }
        /* AT指令交互(轮询式) */
        switch(state)
        {
            case 1: /* 设置名称 */
                ret = cmd_at_process_poll(&CmdAT, CMD_AT_RESERVE, CMD_AT_WAY_REC_FLAG, "AT+OK\r\n", "AT+NAME=%s\r\n", "ashuai0110");
                if(MW_RET_ERR == ret || MW_RET_TIMEOUT == ret)
                {
                    /* 超时或错误直接结束 */
                    state = 0;
                    MW_ERROR_LOG("cmd_at_process_poll return %s! rsp data:%s", ret == MW_RET_ERR ? "error" : "timeout", cmd_at_rsp_data(&CmdAT));
                }
                else if(MW_RET_OK == ret)
                {
                    /* 成功则进入下一状态 */
                    state = 2;
                }
                break;
            case 2: /* 设置时间 */
                ret = cmd_at_process_poll(&CmdAT, CMD_AT_RESERVE, CMD_AT_WAY_REC_FLAG, "AT+OK\r\n", "AT+TIME=%d\r\n", 1000);
                if(MW_RET_ERR == ret || MW_RET_TIMEOUT == ret)
                {
                    /* 超时或错误直接结束 */
                    state = 0;
                    MW_ERROR_LOG("cmd_at_process_poll return %s! rsp data:%s", ret == MW_RET_ERR ? "error" : "timeout", cmd_at_rsp_data(&CmdAT));
                }
                else if(MW_RET_OK == ret)
                {
                    /* 成功则结束 */
                    state = 0;
                }
                break;
        }
#else
        /* 接收完成 */
        if(MW_RET_OK == ret)
        {
            MW_DEBUG_LOG("uart rec complate");
        } /* 接收超时 无需求可忽略此返回值 */
        else if(MW_RET_TIMEOUT == ret)
        {
            MW_WARN_LOG("uart rec timeout");
        }
        /* AT指令交互(轮询式) */
        switch(state)
        {
            case 1: /* 设置名称 */
                ret = cmd_at_process_poll(&CmdAT, CMD_AT_RESERVE, CMD_AT_WAY_SEARCH, "AT+OK\r\n", "AT+NAME=%s\r\n", "ashuai0110");
                if(MW_RET_ERR == ret || MW_RET_TIMEOUT == ret)
                {
                    /* 超时或错误直接结束 */
                    state = 0;
                    MW_ERROR_LOG("cmd_at_process_poll return %s! rsp data:%s", ret == MW_RET_ERR ? "error" : "timeout", cmd_at_rsp_data(&CmdAT));
                }
                else if(MW_RET_OK == ret)
                {
                    /* 成功则进入下一状态 */
                    state = 2;
                }
                break;
            case 2: /* 设置时间 */
                ret = cmd_at_process_poll(&CmdAT, CMD_AT_RESERVE, CMD_AT_WAY_SEARCH, "AT+OK\r\n", "AT+TIME=%d\r\n", 1000);
                if(MW_RET_ERR == ret || MW_RET_TIMEOUT == ret)
                {
                    /* 超时或错误直接结束 */
                    state = 0;
                    MW_ERROR_LOG("cmd_at_process_poll return %s! rsp data:%s", ret == MW_RET_ERR ? "error" : "timeout", cmd_at_rsp_data(&CmdAT));
                }
                else if(MW_RET_OK == ret)
                {
                    /* 成功则结束 */
                    state = 0;
                }
                break;
        }
#endif
        
    }
}

